<template>
  <!-- 时间轴组件容器 -->
  <div class="time-line">
    <!-- 进度条容器，绑定点击、鼠标移动和鼠标离开事件 -->
    <div class="progress-box" @click="seek($event)" @mousemove="showTimeOnHover($event)" @mouseleave="hideTimeLabel">
      <!-- 进度条，根据 progress 值动态设置宽度 -->
      <div class="progress" :style="{ width: progress + '%' }">
        <!-- 显示当前时间的标签 -->
        <div class="time-label">
          <span>{{ currentTime }}</span>
        </div>
      </div>
      <!-- 动态设置样式，鼠标悬停时显示对应位置的时间 -->
      <div class="hover-time" v-if="showHoverTime" :style="{ left: hoverX + 'px'}">
        <span>{{ hoverTime }}</span>
      </div>
      <!-- 显示开始时间 -->
      <div class="start-time">{{ startTime }}</div>
      <!-- 显示结束时间 -->
      <div class="end-time">{{ endTime }}</div>
    </div>

    <!-- 播放/暂停按钮 -->
    <el-icon class="time-line-btn" @click="playOrPause">
      <!-- 未播放时显示播放图标 -->
      <VideoPlay v-if="!playing" />
      <!-- 播放时显示暂停图标 -->
      <VideoPause v-else />
    </el-icon>

    <!-- 速度选择器 -->
    <div class="speed">
      <el-select v-model="speed" placeholder="Select" style="width: 80px">
        <!-- 遍历选项数组，生成下拉选项 -->
        <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
      </el-select>
    </div>
  </div>
</template>
<script setup lang='ts'>
import { ref, onMounted, onUnmounted, watch, computed } from 'vue'
import { VideoPlay, VideoPause } from '@element-plus/icons-vue'
import { sseQuery } from '@/api/sse'
import dayjs from 'dayjs'
import { useAuthStore } from '@/store/auth'
import { storeToRefs } from 'pinia'
import emiter from '@/utils/mitt'
// 播放速度，初始值为 1
const speed = ref('1')
// 速度选项数组
const options = [
  { value: '1', label: '正常' },
  { value: '2', label: '2倍' },
  { value: '4', label: '4倍' },
  { value: '8', label: '8倍' },
  { value: '16', label: '16倍' },
  { value: '32', label: '32倍' },
  { value: '64', label: '64倍' }
]

const authStore = useAuthStore()
const { globalParams, modeParams } = storeToRefs(authStore)
// 播放状态，初始为未播放
const playing = ref(false)
// 时间轴的开始时间
const startTime = computed(() => {
  return globalParams.value.startTime
})
// 时间轴的结束时间
const endTime = computed(() => {
  return globalParams.value.endTime
})
// 进度条的进度，初始为 0
const progress = ref(0)
// 当前时间，初始为开始时间
const currentTime = ref(startTime.value)

// 定时器，用于定时更新时间
let interval: NodeJS.Timer | null = null
let seInterval: NodeJS.Timer | null = null
// 播放开始的时间戳
let playStartTime: number | null = null
// 初始的当前时间戳
let initialCurrentTime: number | null = null

/**
 * 切换播放/暂停状态
 */
function playOrPause () {
  // 切换播放状态
  playing.value = !playing.value
  if (playing.value) {
    // 开始播放
    startPlay()
  } else {
    // 停止播放
    stopPlay()
  }
}

/**
 * 开始播放
 */
let isEnd = false
function startPlay () {
  emiter.emit('timePlay', isEnd)
  if (isEnd) {
    progress.value = 0
    currentTime.value = dayjs(startTime.value).format('YYYY-MM-DD HH:mm')
    isEnd = false
  }
  playing.value = true;
  // 获取开始时间的时间戳
  const start = new Date(startTime.value).getTime();
  // 获取结束时间的时间戳
  const end = new Date(endTime.value).getTime();
  // 记录播放开始的时间戳
  playStartTime = Date.now();
  // 记录初始的当前时间戳
  initialCurrentTime = new Date(currentTime.value).getTime();
  // 每隔 100 毫秒更新一次时间
  interval = setInterval(() => {
    // 如果播放开始时间或初始当前时间为空，则返回
    if (playStartTime === null || initialCurrentTime === null) return;
    // 计算从播放开始到现在经过的真实时间
    const elapsedRealTime = Date.now() - playStartTime;
    // 计算新的时间
    const newTime = initialCurrentTime + (parseFloat(speed.value) * elapsedRealTime * 60);

    if (newTime >= end) {
      isEnd = true
      // 时间到达结束时间，停止播放
      stopPlay();
      // 进度条进度设置为 100%
      progress.value = 100;
      // 当前时间设置为结束时间
      currentTime.value = endTime.value;
    } else {
      // 计算进度条进度
      progress.value = ((newTime - start) / (end - start)) * 100;
      // 更新当前时间
      currentTime.value = dayjs(newTime).format('YYYY-MM-DD HH:mm');
    }

    emiter.emit('timeProgress', {progress: progress.value, currentTime: currentTime.value})
  }, 100);

  if(!globalParams.value.areaId) {
    // 每隔 5 秒查询一次数据
    sseQuery({
      clientId: globalParams.value.clientId,
      dataType: modeParams.value.menu,
      startTime: dayjs(currentTime.value).format('YYYY-MM-DD HH:mm:00'),
      endTime: dayjs(currentTime.value).format('YYYY-MM-DD HH:mm:59'),
    })
    seInterval = setInterval(() => {
      sseQuery({
        clientId: globalParams.value.clientId,
        dataType: modeParams.value.menu,
        startTime: dayjs(currentTime.value).format('YYYY-MM-DD HH:mm:00'),
        endTime: dayjs(currentTime.value).format('YYYY-MM-DD HH:mm:59'),
      })
    }, 5000)
  } else {
    authStore.setHistoryParams({
      startTime: dayjs(currentTime.value).format('YYYY-MM-DD HH:mm:00'),
      endTime: dayjs(currentTime.value).format('YYYY-MM-DD HH:mm:59'),
    })
    seInterval = setInterval(() => {
      authStore.setHistoryParams({
        startTime: dayjs(currentTime.value).format('YYYY-MM-DD HH:mm:00'),
        endTime: dayjs(currentTime.value).format('YYYY-MM-DD HH:mm:59'),
      })
    }, 5000)
    
  }
}
/**
 * 停止播放
 */
function stopPlay () {
  playing.value = false;
  emiter.emit('timePause')
  if (interval) {
    // 清除定时器
    clearInterval(interval);
    clearInterval(seInterval);
    interval = null;
    // 重置播放开始时间和初始当前时间
    playStartTime = null;
    initialCurrentTime = null;
  }
}

// 监听倍速变化，若正在播放则重新开始播放
watch(speed, () => {
  if (playing.value) {
    stopPlay();
    startPlay();
  }
});

// 鼠标悬停时是否显示时间，初始为不显示
const showHoverTime = ref(false)
// 鼠标悬停位置对应的时间
const hoverTime = ref('')
// 存储鼠标位置的 x 坐标
const hoverX = ref(0)

/**
 * 鼠标移动时显示对应位置的时间
 * @param event - 鼠标事件对象
 */
function showTimeOnHover(event: MouseEvent) {
  // 获取进度条容器的边界矩形
  const rect = (event.target as HTMLElement).getBoundingClientRect()
  // 计算鼠标在进度条容器内的 x 坐标
  const x = event.clientX - rect.left
  // 获取进度条容器的宽度
  const width = rect.width
  // 计算新的进度
  const newProgress = (x / width) * 100

  // 获取开始时间的时间戳
  const start = new Date(startTime.value).getTime()
  // 获取结束时间的时间戳
  const end = new Date(endTime.value).getTime()
  // 计算鼠标位置对应的时间
  const newTime = start + ((end - start) * newProgress / 100)

  // 更新鼠标悬停位置对应的时间
  hoverTime.value = dayjs(newTime).format('YYYY-MM-DD HH:mm')
  // 显示鼠标悬停时的时间标签
  showHoverTime.value = true
  // 更新鼠标位置的 x 坐标
  hoverX.value = event.offsetX
}

/**
 * 鼠标离开时隐藏时间标签
 */
function hideTimeLabel() {
  // 隐藏鼠标悬停时的时间标签
  showHoverTime.value = false
}

/**
 * 点击进度条跳转时间
 * @param event - 鼠标事件对象
 */
function seek (event: MouseEvent) {
  let oldPlaying = playing.value;
  if (playing.value) {
    // 若正在播放，先停止播放
    stopPlay()
  }
  // 获取进度条容器的边界矩形
  const rect = (event.target as HTMLElement).getBoundingClientRect()
  // 计算鼠标在进度条容器内的 x 坐标
  const x = event.clientX - rect.left
  // 获取进度条容器的宽度
  const width = rect.width
  // 计算新的进度
  const newProgress = (x / width) * 100

  // 获取开始时间的时间戳
  const start = new Date(startTime.value).getTime()
  // 获取结束时间的时间戳
  const end = new Date(endTime.value).getTime()
  // 计算点击位置对应的时间
  const newTime = start + ((end - start) * newProgress / 100)

  // 更新进度条进度
  progress.value = newProgress
  // 更新当前时间
  currentTime.value = dayjs(newTime).format('YYYY-MM-DD HH:mm')
  if (oldPlaying) {
    // 若之前处于播放状态，重新开始播放
    startPlay()
  }
  emiter.emit('timeSeek', progress.value)
  emiter.emit('timeProgress', progress.value)
}

/**
 * 组件挂载时执行的钩子函数
 */
onMounted(() => {
  // 初始化时可能需要的操作
  setTimeout(() => {
    startPlay()
  }, 5000)
})

emiter.on('changeScene', () => {
  stopPlay()
  progress.value = 0
  currentTime.value = dayjs(startTime.value).format('YYYY-MM-DD HH:mm')
  startPlay()
})

/**
 * 组件卸载时执行的钩子函数
 */
onUnmounted(() => {
  // 停止播放
  stopPlay()
})

</script>
<style lang="scss" scoped>
.time-line {
  // 横向排列子元素，并在两端对齐
  display: flex;
  justify-content: space-between;
  // 垂直居中对齐子元素
  align-items: center;
  // 子元素之间的间距为 16px
  gap: 16px;

  .progress-box {
    // 进度条容器的高度为 8px
    height: 8px;
    // 占据剩余的可用空间
    flex: 1;
    // 背景颜色，半透明绿色
    background-color: rgba(7, 187, 133, 0.1);
    // 相对定位，用于子元素的绝对定位
    position: relative;
    // 字体大小为 12px
    font-size: 12px;
    // 鼠标指针样式为手型
    cursor: pointer;

    .start-time {
      transform: translateX(-50%);
      position: absolute;
      bottom: -30px;
      left: 0;
      // 透明度为 0.5
      opacity: 0.5;
    }

    .end-time {
      // 绝对定位，位于容器顶部上方 30px，右侧 0 位置
      transform: translateX(50%);
      position: absolute;
      bottom: -30px;
      right: 0;
      // 透明度为 0.5
      opacity: 0.5;
    }

    .hover-time{
      // 绝对定位
      position: absolute;
      // 水平居中对齐
      transform: translateX(-50%);
      // 文本不换行
      white-space: nowrap;
      bottom: 10px;
      color: var(--text-color-placeholder)
    }

    .progress {
      // 禁止鼠标事件
      pointer-events: none;
      // 相对定位，用于子元素的绝对定位
      position: relative;
      // 背景颜色，Element Plus 主题色的浅色变体
      background-color: var(--el-color-primary-light-5);
      // 过渡动画，所有属性变化在 0.3 秒内完成，缓出效果
      transition: all 0.3s ease-out 0s;
      // 进度条高度为 8px
      height: 8px;
      // 初始宽度为 50%
      width: 50%;

      .time-label {
        // 显示元素
        display: block;
        // 绝对定位
        position: absolute;
        // 文本不换行
        white-space: nowrap;
        // 位于容器顶部上方 30px
        top: -30px;
        // 右侧对齐
        right: 0;
        // 水平向右偏移 50%
        transform: translateX(50%);
      }

      &::after {
        // 显示伪元素
        display: block;
        // 伪元素内容为空
        content: '';
        // 绝对定位
        position: absolute;
        // 位于容器顶部上方 4px
        top: -4px;
        // 右侧对齐
        right: 0;
        // 宽度为 4px
        width: 4px;
        // 高度为 16px
        height: 16px;
        // 背景颜色为白色
        background-color: #fff;
      }
    }

    .btn {
      // 按钮背景颜色，Element Plus 主题色的浅色变体
      background-color: var(--el-color-primary-light-5);
    }
  }

  .time-line-btn {
    // 图标字体大小为 24px
    font-size: 24px;
    // 图标颜色，Element Plus 主题色的浅色变体
    color: var(--el-color-primary-light-5);
    // 鼠标指针样式为手型
    cursor: pointer;
  }
}
</style>
